package com.zpp.gobang.game;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zpp.gobang.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

//这个类表示“匹配器”，通过这个类负责完成整个匹配的功能更
@Component
public class Matcher {
    //创建三个匹配队列
    /**
     * normal     score < 2000
     * high       score >= 2000 && score < 3000
     * veryHigh   score >= 3000
     */

    private Queue<User> normalQueue = new LinkedList<>();
    private Queue<User> highQueue = new LinkedList<>();
    private Queue<User> veryHighQueue = new LinkedList<>();

    @Autowired
    private OnlineUserManager onlineUserManager;

    @Autowired
    private RoomManager roomManager;

    @Autowired
    private ObjectMapper objectMapper;

    //操作匹配队列方法
    //把玩家加入匹配队列中
    public void add(User user){
        if(user.getScore() < 2000){
            synchronized (normalQueue){  //多线程加锁保证线程安全
                normalQueue.offer(user);
                normalQueue.notify();
            }
            System.out.println("玩家 "+ user.getUsername()+" 进入normalQueue匹配队列");
        }else if(user.getScore() < 3000){
            synchronized (highQueue){
                highQueue.offer(user);
                highQueue.notify();
            }
            System.out.println("玩家 "+ user.getUsername()+" 进入highQueue匹配队列");
        }else {
            synchronized (veryHighQueue){
                veryHighQueue.offer(user);
                veryHighQueue.notify();
            }
            System.out.println("玩家 "+ user.getUsername()+" 进入veryHighQueue匹配队列");
        }
    }

    //把玩家从匹配队列中移除
    public void remove(User user){
        if(user.getScore() < 2000){
            synchronized (normalQueue){
                normalQueue.remove(user);
            }
            System.out.println("玩家 "+ user.getUsername()+" 离开normalQueue匹配队列");
        }else if(user.getScore() < 3000){
            synchronized (highQueue){
                highQueue.remove(user);
            }
            System.out.println("玩家 "+ user.getUsername()+" 离开highQueue匹配队列");
        }else {
            synchronized (veryHighQueue){
                veryHighQueue.remove(user);
            }
            System.out.println("玩家 "+ user.getUsername()+" 离开veryHighQueue匹配队列");
        }
    }

    //构造方法 开启三哥线程  不断扫描三个匹配队列中的用户
    public Matcher(){
        Thread t1 = new Thread(){
            @Override
            public void run() {
                while(true){
                    handlerMatch(normalQueue);
                }

            }
        };
        t1.start();

        Thread t2 = new Thread(){
            @Override
            public void run() {
                while(true){
                    handlerMatch(highQueue);
                }

            }
        };
        t2.start();

        Thread t3 = new Thread(){
            @Override
            public void run() {
                while(true){
                    handlerMatch(veryHighQueue);
                }

            }
        };
        t3.start();
    }

    private void handlerMatch(Queue<User> matchQueue) {
        synchronized (matchQueue){

            try {
                //1.队列中人数至少要有两人才能开始游戏
                while (matchQueue.size() < 2){
                    matchQueue.wait();
                }
                //2.取出两个用户
                User user1 = matchQueue.poll();
                User user2 = matchQueue.poll();
                System.out.println("匹配到两个玩家 "+ user1.getUsername() + ", " + user2.getUsername());

                //3.获取玩家的websocket会话
                WebSocketSession session1 = onlineUserManager.getFromGameHall(user1.getUserId());
                WebSocketSession session2 = onlineUserManager.getFromGameHall(user2.getUserId());
                //如果存在某一玩家已经离线退出，则把另一玩家继续加到队列中匹配
                if(session1 == null){
                    matchQueue.offer(user2);
                    return;
                }
                if(session2 == null){
                    matchQueue.offer(user1);
                    return;
                }
                //如果两个信息是同一个玩家，则把该玩家继续加到匹配队列中匹配
                if(session1 == session2){
                    matchQueue.offer(user1);
                    return;
                }

                //4. 把这个两个玩家放到一个游戏房间中
                Room room = new Room();
                roomManager.add(room,user1.getUserId(),user2.getUserId());

                //5.给玩家返回信息，表示已经匹配到对手了
                MatchResponse response1 = new MatchResponse();
                response1.setOk(true);
                response1.setMessage("matchSuccess");
                String json1 = objectMapper.writeValueAsString(response1);
                session1.sendMessage(new TextMessage(json1));

                MatchResponse response2 = new MatchResponse();
                response2.setOk(true);
                response2.setMessage("matchSuccess");
                String json2 = objectMapper.writeValueAsString(response2);
                session2.sendMessage(new TextMessage(json2));

            }catch (IOException e){
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}
